package nsoft.swing.component;

import java.util.regex.Pattern;

import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.DocumentFilter;

public class NDocumentFilter extends DocumentFilter {

	/**
	 * serialVersionUID = 1L.
	 */
	private static final long serialVersionUID = 1L;
	private String pattern = null;
	private Long length;
	private Short decimals;
	private Short integrals;

	public NDocumentFilter(String pattern) {
		this.pattern = pattern;
	}

	public NDocumentFilter(String pattern, Long length) {
		this(pattern, length, null, null);
	}

	public NDocumentFilter(String pattern, Short decimals) {
		this(pattern, null, decimals, null);
	}

	public NDocumentFilter(String pattern, Short decimals, Short integrals) {
		this(pattern, null, decimals, integrals);
	}

	public NDocumentFilter(String pattern, Long length, Short decimals,
			Short integrals) {
		this.pattern = pattern;
		this.length = length;
		this.decimals = decimals;
		this.integrals = integrals;
	}

	@Override
	public void replace(FilterBypass fb, int offs, int length, String str,
			AttributeSet a) throws BadLocationException {
		if (str == null) {
			return;
		}
		if (pattern == null) {
			super.replace(fb, offs, length, str, a);
		} else {
			String oldString = fb.getDocument().getText(0,
					fb.getDocument().getLength());
			String newString = oldString.substring(0, offs) + str
					+ oldString.substring(offs + length);
			if (Pattern.matches(pattern, newString)
					&& validateLength(newString)) {
				super.replace(fb, offs, length, str, a);

			}
		}
		update(fb.getDocument());
	}

	@Override
	public void remove(FilterBypass fb, int offset, int length)
			throws BadLocationException {
		super.remove(fb, offset, length);
		update(fb.getDocument());
	}

	private boolean validateLength(String value) {
		boolean valied = true;
		if (length != null) {
			valied = value.length() <= length;
		}
		if (valied && decimals != null) {
			if (value.indexOf('.') > 0) {
				valied = value.substring(value.indexOf('.') + 1).length() <= decimals;
			}
		}
		if (valied && integrals != null) {
			if (value.indexOf('.') > 0) {
				valied = value.substring(0, value.indexOf('.') - 1).length() <= integrals;
			} else {
				valied = value.length() <= integrals;
			}
		}
		return valied;
	}

	private void update(Document doc) {
		if (doc instanceof BeanBinder) {
			((BeanBinder) doc).updateBean();
		}
	}

	public String getPattern() {
		return pattern;
	}

	public void setPattern(String pattern) {
		this.pattern = pattern;
	}

	public Long getLength() {
		return length;
	}

	public void setLength(Long length) {
		this.length = length;
	}

	public Short getDecimals() {
		return decimals;
	}

	public void setDecimals(Short decimals) {
		this.decimals = decimals;
	}

	public Short getIntegrals() {
		return integrals;
	}

	public void setIntegrals(Short integrals) {
		this.integrals = integrals;
	}

}
